<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="Java 8 Stream API详解( 三)——Stream操作, 码道诚公">
    <meta name="description" content="">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="baidu-site-verification" content="code-oqVlgh2wQV" />
    <meta name="google-site-verification" content="Z-8Fm46WY6NL_3kxilmoqToW4jnvyF7boTgciTLBXUs" />
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>Java 8 Stream API详解( 三)——Stream操作 | 码道诚公</title>
    <link rel="icon" type="image/png" href="/favicon.png">

    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">

    <script src="/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 5.2.0">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
<link rel="alternate" href="/atom.xml" title="码道诚公" type="application/atom+xml">
<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>




<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <img src="/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">码道诚公</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">码道诚公</div>
        <div class="logo-desc">
            
            Never really desperate, only the lost of the soul.
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
    </ul>
</div>


        </div>

        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/medias/featureimages/4.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">Java 8 Stream API详解( 三)——Stream操作</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="container content">

    
    <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/Java-Stream/">
                                <span class="chip bg-color">Java Stream</span>
                            </a>
                        
                            <a href="/tags/%E5%87%BD%E6%95%B0%E5%BC%8F/">
                                <span class="chip bg-color">函数式</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/categories/Java/" class="post-category">
                                Java
                            </a>
                        
                            <a href="/categories/Java/Stream/" class="post-category">
                                Stream
                            </a>
                        
                            <a href="/categories/Java/Stream/%E5%87%BD%E6%95%B0%E5%BC%8F/" class="post-category">
                                函数式
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2021-01-18
                </div>
                

                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    5.3k
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-clock fa-fw"></i>阅读时长:&nbsp;&nbsp;
                    23 分
                </div>
                

                
            </div>
        </div>
        <hr class="clearfix">
        <div class="card-content article-card-content">
            <div id="articleContent">
                <p>在流上可以执行很多操作，这些操作分为中间操作（返回Stream）和终结操作（返回确定类型的结果），中间操作允许链式串接。要注意，流上的操作不会改变数据源。<br>如下例：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">long</span> count <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">distinct</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>这里的_distinct()_方法就是一个内部操作，会在之前流的基础上创建一个元素唯一的新流，而_count()_方法就是一个终结操作，会返回流的大小。</p>
<h2 id="Stream-操作"><a href="#Stream-操作" class="headerlink" title="Stream 操作"></a>Stream 操作</h2><h3 id="迭代-Iterating"><a href="#迭代-Iterating" class="headerlink" title="迭代 Iterating"></a>迭代 <strong>Iterating</strong></h3><p>Stream API可以替换for、for-each、while循环，使用该方法，开发者可以专注于操作的逻辑，而无需关心元素序列的迭代。如：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">for</span> <span class="token punctuation">(</span>String string <span class="token operator">:</span> list<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>string<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>转换为Stream风格只需一行代码：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">boolean</span> isExist <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">anyMatch</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="过滤-Filtering"><a href="#过滤-Filtering" class="headerlink" title="过滤 Filtering"></a>过滤 Filtering</h3><p>filter()方法可用于挑选满足断言的流元素，举例来说，如果有一个这样的流：</p>
<pre class=" language-java"><code class="language-java">ArrayList<span class="token operator">&lt;</span>String<span class="token operator">></span> list <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"One"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"OneAndOnly"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"Derek"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"Change"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"factory"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"justBefore"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"Italy"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"Italy"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"Thursday"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>下面的代码会创建该列表对应的一个字符串流，找到流中所有包含字符“d”的元素，并将过滤出的元素组成一个新的流：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> stream <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"d"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="映射-Mapping"><a href="#映射-Mapping" class="headerlink" title="映射 Mapping"></a><strong>映射 Mapping</strong></h3><p>如果需要对流中的元素执行特定的函数进行转换，并将转换后的新元素收集到新的流中，可以使用_map()_方法：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> uris <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
uris<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"C:\\My.txt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Stream<span class="token operator">&lt;</span>Path<span class="token operator">></span> stream <span class="token operator">=</span> uris<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>uri <span class="token operator">-</span><span class="token operator">></span> Paths<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>uri<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>上面的代码会对初始流中的每个元素执行指定的lambda表达式，将Stream<string>转换为Stream<path>。<br>如果有一个流，其中每个元素都包含其对应的一串元素序列，要根据所有内部元素创建一个新流，应该使用_flatMap()_方法：</path></string></p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Detail<span class="token operator">></span> details <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
details<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Detail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> stream <span class="token operator">=</span> details<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>detail <span class="token operator">-</span><span class="token operator">></span> detail<span class="token punctuation">.</span><span class="token function">getParts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>在这个例子中，我们有一个元素为Detail类的列表，Detail类中包含字段PARTS，是一个字符串列表。通过使用flatMap()方法，字段PARTS中的每一个元素都被提取出来并添加到新的结果流中，之后，初始的Stream<detail>会被丢弃。</detail></p>
<h3 id="匹配-Matching"><a href="#匹配-Matching" class="headerlink" title="匹配 Matching"></a><strong>匹配 Matching</strong></h3><p>Stream API提供了一组方便的工具来根据某些断言验证一系列元素，要实现该目标，可以使用以下三个方法之一：_anyMatch(), allMatch(), noneMatch()，_每个函数的功能都一目了然，这些都是返回布尔值的终结操作：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">boolean</span> isValid <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">anyMatch</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"h"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// true</span>
<span class="token keyword">boolean</span> isValidOne <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allMatch</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"h"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// false</span>
<span class="token keyword">boolean</span> isValidTwo <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">noneMatch</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"h"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// false</span></code></pre>
<p>如果是空流，对于任意给定的断言，_allMatch()_方法都会返回true：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allMatch</span><span class="token punctuation">(</span>Objects<span class="token operator">:</span><span class="token operator">:</span>nonNull<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// true</span></code></pre>
<p>这是一个合理的默认值，因为我们找不到任何不满足断言的元素。<br>同样的，对于空流，<em>anyMatch()</em> 方法一定会返回false：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">anyMatch</span><span class="token punctuation">(</span>Objects<span class="token operator">:</span><span class="token operator">:</span>nonNull<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// false</span></code></pre>
<p>同样，这也是合理的，因为我们找不到满足该条件的元素。</p>
<h3 id="归集-Reduction"><a href="#归集-Reduction" class="headerlink" title="归集 Reduction"></a><strong>归集 Reduction</strong></h3><p>Stream API中使用reduce()方法可以根据指定的方法将一系列元素归集为某个值，该方法接收两个参数：第一个是初始值，第二个是累加器函数。<br>假设您有一个整数列表，并且想要在某个初始值（这里使用23）基础上计算所有元素的总和，可以运行下面的代码，得到结果为26（23+1+1+1）：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Integer<span class="token operator">></span> integers <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Integer reduced <span class="token operator">=</span> integers<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token number">23</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> a <span class="token operator">+</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="收集-Collecting"><a href="#收集-Collecting" class="headerlink" title="收集 Collecting"></a><strong>收集 Collecting</strong></h3><p>归集操作也可以通过collect()方法实现。在将流转换为集合、映射或使用一个字符串表示一个流时，该操作非常方便。还有一个工具类Collectors，提供了几乎所有常用的收集操作，对于一些复杂的任务，额可以创建自定义收集器。</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> resultList <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>element <span class="token operator">-</span><span class="token operator">></span> element<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>该代码提供最后的collect()方法将字符串流转换为字符串列表。</p>
<h3 id="搜索-Searching"><a href="#搜索-Searching" class="headerlink" title="搜索 Searching"></a>搜索 Searching</h3><p>在集合中的搜索意味着根据一个条件查找元素或验证元素的存在性，这个条件也叫做谓词或断言。搜索元素可能有返回值，也可能没有，所以接口返回的是一个Optional；验证元素存在性时返回是的一个布尔值。<br>下面的示例中，通过findAny()查找元素，通过anyMatch()检查是否存在满足条件的元素。</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">// searching for a element</span>
Optional<span class="token operator">&lt;</span>Person<span class="token operator">></span> any <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>person <span class="token operator">-</span><span class="token operator">></span> person<span class="token punctuation">.</span><span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">20</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">findAny</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">// searching for existence</span>
<span class="token keyword">boolean</span> isAnyOneInGroupLessThan20Years <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">anyMatch</span><span class="token punctuation">(</span>person <span class="token operator">-</span><span class="token operator">></span> person<span class="token punctuation">.</span><span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="重排序-Reordering"><a href="#重排序-Reordering" class="headerlink" title="重排序 Reordering"></a>重排序 Reordering</h3><p>如果需要对集合中的元素进行排序，可以使用Stream中的sorted方法，该方法接收一个Comparator接口的实现类作为参数。可以使用Comparator中的comparing工厂方法来创建对应的实例。<br>在下面的代码中，结果就是按照Person的age属性降序排列后的集合。</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Person<span class="token operator">></span> peopleSortedEldestToYoungest <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">sorted</span><span class="token punctuation">(</span>Comparator<span class="token punctuation">.</span><span class="token function">comparing</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reversed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<blockquote>
<p>与我们之前讨论的其它操作不同，排序操作是有状态的。这也就意味着，在将排序结果传递给后续的中间操作或终结操作时，该操作方法必须处理流中的所有元素。还有另一个类似的操作，就是_distinct_。</p>
</blockquote>
<h3 id="汇总-Summarizing"><a href="#汇总-Summarizing" class="headerlink" title="汇总 Summarizing"></a>汇总 Summarizing</h3><p>有时我们需要从集合中提取一些信息。比如，提取所有用户的年龄的总和，在Stream API中，可以使用终结操作。reduce和collect就是为此目的提供的通用终结操作。还有一些在其基础上创建的高级运算符，如sum、count、summaryStatistics等。</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">// calculating sum using reduce terminal operator</span>
people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>total<span class="token punctuation">,</span> currentValue<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> total <span class="token operator">+</span> currentValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// calculating sum using sum terminal operator</span>
people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// calculating count using count terminal operator</span>
people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// calculating summary</span>
IntSummaryStatistics ageStatistics <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">summaryStatistics</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ageStatistics<span class="token punctuation">.</span><span class="token function">getAverage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ageStatistics<span class="token punctuation">.</span><span class="token function">getCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ageStatistics<span class="token punctuation">.</span><span class="token function">getMax</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ageStatistics<span class="token punctuation">.</span><span class="token function">getMin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ageStatistics<span class="token punctuation">.</span><span class="token function">getSum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<blockquote>
<p>reduce和collect是归集操作，reduce用于不可变归集，而collect用于可变的归集。不可变归集是首选的方法，但是对于重视性能的场景，应该优先选择可变收集。</p>
</blockquote>
<h3 id="分组-Grouping"><a href="#分组-Grouping" class="headerlink" title="分组 Grouping"></a>分组 Grouping</h3><p>分组也可以称为分类。有时，我们希望将一个集合分成几个组，在这种情况下产生的数据结构是一个Map，其中key表示分组因子，值为各组对应的属性。Stream API对于此类场景提供了_Collectors.groupingBy_方法。<br>在下面的例子中，都是要性别对数据进行分组，区别之处在于值。第一个例子中，为每个组创建了Person集合；第二个例子中，通过_Collectors.mapping()_是提取每个用户的姓名，并创建姓名集合；第三个例子中，提取并计算每组的平均年龄。</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">// Grouping people by gender</span>
Map<span class="token operator">&lt;</span>Gender<span class="token punctuation">,</span> List<span class="token operator">&lt;</span>Person<span class="token operator">>></span> peopleByGender <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">groupingBy</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getGender<span class="token punctuation">,</span> Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Grouping person names by gender</span>
Map<span class="token operator">&lt;</span>Gender<span class="token punctuation">,</span> List<span class="token operator">&lt;</span>String<span class="token operator">>></span> nameByGender <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">groupingBy</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getGender<span class="token punctuation">,</span> Collectors<span class="token punctuation">.</span><span class="token function">mapping</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getName<span class="token punctuation">,</span> Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Grouping average age by gender</span>
Map<span class="token operator">&lt;</span>Gender<span class="token punctuation">,</span> Double<span class="token operator">></span> averageAgeByGender <span class="token operator">=</span> people<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">groupingBy</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getGender<span class="token punctuation">,</span> Collectors<span class="token punctuation">.</span><span class="token function">averagingInt</span><span class="token punctuation">(</span>Person<span class="token operator">:</span><span class="token operator">:</span>getAge<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h1 id="常见案例"><a href="#常见案例" class="headerlink" title="常见案例"></a>常见案例</h1><h2 id="在forEach循环中break"><a href="#在forEach循环中break" class="headerlink" title="在forEach循环中break"></a>在forEach循环中break</h2><p>对一组元素进行遍历并对其中元素执行操作时，可以通过Stream中的forEach方法以干净、声明式的方式编写出代码。虽然这与循环是类似的，但是缺少了与break对应的终止迭代的语句。一个流可能很长，甚至是无限的，如果不需要继续对其进行处理，我们希望可以直接终止操作，而不是等到处理完所有元素。</p>
<h4 id="使用自定义Spliterator"><a href="#使用自定义Spliterator" class="headerlink" title="使用自定义Spliterator"></a>使用自定义<em>Spliterator</em></h4><p>在Java 8中引入的Spliterator接口（可拆分迭代器）可用于对序列进行遍历和分区。它是流（尤其是并行流）的基本工具类。<br>tryAdvance()是单步遍历序列的主要方法。该方法接收一个Consumer作为参数，该消费者用于持续消费spliterator的元素，如果没有可遍历的元素则返回false。<br>我们可以创建一个自定义的<em>Spliterator</em> 作为_Stream.spliterator_的装饰器，并以此完成break操作。<br>首先，我们需要获取流的_Spliterator_并使用自定义的_CustomSpliterator_对其进行装饰，这里需要提供控制_break_行为的断言，最后我们再根据_CustomSpliterator_创建新流：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CustomTakeWhile</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token operator">&lt;</span>T<span class="token operator">></span> Stream<span class="token operator">&lt;</span>T<span class="token operator">></span> <span class="token function">takeWhile</span><span class="token punctuation">(</span>Stream<span class="token operator">&lt;</span>T<span class="token operator">></span> stream<span class="token punctuation">,</span> Predicate<span class="token operator">&lt;</span>T<span class="token operator">></span> predicate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        CustomSpliterator<span class="token operator">&lt;</span>T<span class="token operator">></span> customSpliterator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CustomSpliterator</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span>stream<span class="token punctuation">.</span><span class="token function">spliterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> predicate<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> StreamSupport<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span>customSpliterator<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>下面是_CustomSpliterator_的代码：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CustomSpliterator</span><span class="token operator">&lt;</span>T<span class="token operator">></span> <span class="token keyword">extends</span> <span class="token class-name">Spliterators<span class="token punctuation">.</span>AbstractSpliterator</span><span class="token operator">&lt;</span>T<span class="token operator">></span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> Spliterator<span class="token operator">&lt;</span>T<span class="token operator">></span> splitr<span class="token punctuation">;</span>
    <span class="token keyword">private</span> Predicate<span class="token operator">&lt;</span>T<span class="token operator">></span> predicate<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">boolean</span> isMatched <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">CustomSpliterator</span><span class="token punctuation">(</span>Spliterator<span class="token operator">&lt;</span>T<span class="token operator">></span> splitr<span class="token punctuation">,</span> Predicate<span class="token operator">&lt;</span>T<span class="token operator">></span> predicate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">super</span><span class="token punctuation">(</span>splitr<span class="token punctuation">.</span><span class="token function">estimateSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>splitr <span class="token operator">=</span> splitr<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>predicate <span class="token operator">=</span> predicate<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">boolean</span> <span class="token function">tryAdvance</span><span class="token punctuation">(</span>Consumer<span class="token operator">&lt;</span><span class="token operator">?</span> <span class="token keyword">super</span> T<span class="token operator">></span> consumer<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">boolean</span> hadNext <span class="token operator">=</span> splitr<span class="token punctuation">.</span><span class="token function">tryAdvance</span><span class="token punctuation">(</span>elem <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>predicate<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>elem<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> isMatched<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                consumer<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span>elem<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
                isMatched <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> hadNext <span class="token operator">&amp;&amp;</span> isMatched<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>可以看到上面的tryAdvance()方法，自定义的拆分器处理了装饰的拆分器中的元素，只要断言为真并且初始流中还有元素，就会一直进行处理；如果两个条件中任意为false，拆分器就会break，流操作也会结束。<br>假设我们有一个字符串项流，只要其中元素的长度是奇数，我们就持续处理其元素。测试代码如下：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCustomTakeWhileIsCalled_ThenCorrectItemsAreReturned</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> initialStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">,</span> <span class="token string">"elephant"</span><span class="token punctuation">,</span> <span class="token string">"fox"</span><span class="token punctuation">,</span> <span class="token string">"rabbit"</span><span class="token punctuation">,</span> <span class="token string">"duck"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    List<span class="token operator">&lt;</span>String<span class="token operator">></span> result <span class="token operator">=</span> CustomTakeWhile<span class="token punctuation">.</span><span class="token function">takeWhile</span><span class="token punctuation">(</span>initialStream<span class="token punctuation">,</span> x <span class="token operator">-</span><span class="token operator">></span> x<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="使用自定义forEach"><a href="#使用自定义forEach" class="headerlink" title="使用自定义forEach"></a>使用自定义<em>forEach</em></h4><p>虽然提供嵌入的break机制可能很有用，但是只关注forEach操作可能会更简单。<br>我们可以直接使用<strong><em>Stream.spliterator</em></strong>：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CustomForEach</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Breaker</span> <span class="token punctuation">{</span>
        <span class="token keyword">private</span> <span class="token keyword">boolean</span> shouldBreak <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            shouldBreak <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">boolean</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> shouldBreak<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token operator">&lt;</span>T<span class="token operator">></span> <span class="token keyword">void</span> <span class="token function">forEach</span><span class="token punctuation">(</span>Stream<span class="token operator">&lt;</span>T<span class="token operator">></span> stream<span class="token punctuation">,</span> BiConsumer<span class="token operator">&lt;</span>T<span class="token punctuation">,</span> Breaker<span class="token operator">></span> consumer<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Spliterator<span class="token operator">&lt;</span>T<span class="token operator">></span> spliterator <span class="token operator">=</span> stream<span class="token punctuation">.</span><span class="token function">spliterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">boolean</span> hadNext <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        Breaker breaker <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Breaker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">while</span> <span class="token punctuation">(</span>hadNext <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>breaker<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            hadNext <span class="token operator">=</span> spliterator<span class="token punctuation">.</span><span class="token function">tryAdvance</span><span class="token punctuation">(</span>elem <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span>
                consumer<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span>elem<span class="token punctuation">,</span> breaker<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>可以看到，自定义的forEach方法会调用Biconsumer来处理下一个元素和用于终止流程的breaker。<br>测试代码如下：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCustomForEachIsCalled_ThenCorrectItemsAreReturned</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> initialStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">,</span> <span class="token string">"elephant"</span><span class="token punctuation">,</span> <span class="token string">"fox"</span><span class="token punctuation">,</span> <span class="token string">"rabbit"</span><span class="token punctuation">,</span> <span class="token string">"duck"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    List<span class="token operator">&lt;</span>String<span class="token operator">></span> result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    CustomForEach<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>initialStream<span class="token punctuation">,</span> <span class="token punctuation">(</span>elem<span class="token punctuation">,</span> breaker<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>elem<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            breaker<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            result<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>elem<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="Stream-takeWhile-（Java-9）"><a href="#Stream-takeWhile-（Java-9）" class="headerlink" title="Stream.takeWhile() （Java 9）"></a>Stream.takeWhile() （Java 9）</h4><p>如果使用的是Java 9，可以使用_Stream.takeWhile()_方法，如下：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">,</span> <span class="token string">"elephant"</span><span class="token punctuation">,</span> <span class="token string">"fox"</span><span class="token punctuation">,</span> <span class="token string">"rabbit"</span><span class="token punctuation">,</span> <span class="token string">"duck"</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">takeWhile</span><span class="token punctuation">(</span>n <span class="token operator">-</span><span class="token operator">></span> n<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>System<span class="token punctuation">.</span>out<span class="token operator">:</span><span class="token operator">:</span>println<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>运行结果为：</p>
<pre class=" language-java"><code class="language-java">cat
dog</code></pre>
<p>其等价的循环代码为：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> list <span class="token operator">=</span> <span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"cat"</span><span class="token punctuation">,</span> <span class="token string">"dog"</span><span class="token punctuation">,</span> <span class="token string">"elephant"</span><span class="token punctuation">,</span> <span class="token string">"fox"</span><span class="token punctuation">,</span> <span class="token string">"rabbit"</span><span class="token punctuation">,</span> <span class="token string">"duck"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    String item <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>item<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="过滤Optionals流"><a href="#过滤Optionals流" class="headerlink" title="过滤Optionals流"></a>过滤Optionals流</h2><p>这一节讨论一下如何过滤出Optionals流中的非空值呢？<br>假设我们有一个下面所示的流：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Optional<span class="token operator">&lt;</span>String<span class="token operator">>></span> listOfOptionals <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>Optional<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> Optional<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> Optional<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> Optional<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"bar"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="使用filter"><a href="#使用filter" class="headerlink" title="使用filter()"></a>使用filter()</h4><p>可以使用_Optional::isPresent_过滤所有包含值的_optionals，_如何通过map操作执行_Optional::get_提取出其中的值：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> filteredList <span class="token operator">=</span> listOfOptionals<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>Optional<span class="token operator">:</span><span class="token operator">:</span>isPresent<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>Optional<span class="token operator">:</span><span class="token operator">:</span>get<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="使用flatmap"><a href="#使用flatmap" class="headerlink" title="使用flatmap()"></a>使用flatmap()</h4><p>还有一种方式是将flatMap与lambda函数一起使用，函数会将空的Optional转换为空流，将非空的Optional转换为只包含一个元素的流，然后将流汇聚：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> filteredList <span class="token operator">=</span> listOfOptionals<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>o <span class="token operator">-</span><span class="token operator">></span> o<span class="token punctuation">.</span><span class="token function">isPresent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>o<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">:</span> Stream<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>也可以使用其它的转换方式来实现：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> filteredList <span class="token operator">=</span> listOfOptionals<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>o <span class="token operator">-</span><span class="token operator">></span> o<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>Stream<span class="token operator">:</span><span class="token operator">:</span>of<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">orElseGet</span><span class="token punctuation">(</span>Stream<span class="token operator">:</span><span class="token operator">:</span>empty<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="Optional-stream（Java-9）"><a href="#Optional-stream（Java-9）" class="headerlink" title="Optional::stream（Java 9）"></a>Optional::stream（Java 9）</h4><p>Java9中，向Optional加入了stream方法，简化了上面的操作，其实现与上面flatMap的方式类似，只是换成了系统提供的函数。<br>根据Optional中是否包含值，会将其对应转换为包含一个或零个元素的流。</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>String<span class="token operator">></span> filteredList <span class="token operator">=</span> listOfOptionals<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>Optional<span class="token operator">:</span><span class="token operator">:</span>stream<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="合并不同的流"><a href="#合并不同的流" class="headerlink" title="合并不同的流"></a>合并不同的流</h2><h4 id="使用Java原生接口"><a href="#使用Java原生接口" class="headerlink" title="使用Java原生接口"></a>使用Java原生接口</h4><p>合并两个流的话，可以使用静态方法<em>Stream.concat()</em> ：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenMergingStreams_thenResultStreamContainsElementsFromBoth</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream2 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> resultingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>stream1<span class="token punctuation">,</span> stream2<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">assertEquals</span><span class="token punctuation">(</span>Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>如果要合并的流不止两个，这种方式就稍微复杂一点。可以采用的方法就是，先合并前两个流，然后依次合并后面的流直到全部合并完成。</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given3Streams_whenMerged_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream2 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream3 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> resultingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>
      Stream<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>stream1<span class="token punctuation">,</span> stream2<span class="token punctuation">)</span><span class="token punctuation">,</span> stream3<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">assertEquals</span><span class="token punctuation">(</span>
      Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>可以看到，如果要合并的流比较多，这种方写出的代码是很不优雅的，当然也可以通过创建中间变量或者辅助方法使其更具可读性。<br>但是，我们还有更优雅的方式：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given4Streams_whenMerged_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream2 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream3 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream4 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">99</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> resultingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>
      stream1<span class="token punctuation">,</span> stream2<span class="token punctuation">,</span> stream3<span class="token punctuation">,</span> stream4<span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>i <span class="token operator">-</span><span class="token operator">></span> i<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">assertEquals</span><span class="token punctuation">(</span>
      Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token number">99</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>这里主要分为两步：</p>
<ol>
<li><p>首先创建包含四个流的新流，其结果为_Stream&lt;Stream<integer>&gt;_。</integer></p>
</li>
<li><p>然后使用_flatMap()_和恒定式将其转换为一个_Stream<integer>_。</integer></p>
<h4 id="使用StreamEx"><a href="#使用StreamEx" class="headerlink" title="使用StreamEx"></a>使用StreamEx</h4><p><a target="_blank" rel="noopener" href="https://github.com/amaembo/streamex">StreamEx</a>是一个开源Java库，它对Java 8 中的Streams接口进行了扩展，其使用_StreamEx_类作为对JDK的流接口的增强。<br>StreamEx提供了_append()_方法来合并流：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given4Streams_whenMerged_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream2 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream3 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> stream4 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">99</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> resultingStream <span class="token operator">=</span> StreamEx<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>stream1<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>stream2<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>stream3<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>stream4<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>
   Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token number">99</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
   resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>如果这里的resultingStream类型是StreamEx，可以直接调用toList()方法创建元素列表。<br>StreamEx还提供了prepend()方法，可以将流中元素加在其它流之前：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given3Streams_whenPrepended_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> stream1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token string">"bar"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> openingBracketStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"["</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> closingBracketStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"]"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> resultingStream <span class="token operator">=</span> StreamEx<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>stream1<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>closingBracketStream<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">prepend</span><span class="token punctuation">(</span>openingBracketStream<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>
   Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"["</span><span class="token punctuation">,</span> <span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token string">"bar"</span><span class="token punctuation">,</span> <span class="token string">"]"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
   resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="使用Jooλ"><a href="#使用Jooλ" class="headerlink" title="使用Jooλ"></a>使用Jooλ</h4><p><a target="_blank" rel="noopener" href="https://github.com/jOOQ/jOOL">Jooλ</a>是一个与JDK8兼容的扩展库，其中最重要的流抽象是Seq，表明这是有序流，因此调用_parallel()_方法是无效的。<br>与StreamEx一样，Jooλ中也提供了append()方法：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given2Streams_whenMerged_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> seq1 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> seq2 <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 Stream<span class="token operator">&lt;</span>Integer<span class="token operator">></span> resultingSeq <span class="token operator">=</span> Seq<span class="token punctuation">.</span><span class="token function">ofType</span><span class="token punctuation">(</span>seq1<span class="token punctuation">,</span> Integer<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>seq2<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>
   Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
   resultingSeq<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>当然，既然有append()方法，Jooλ中也提供了prepend()方法：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">given3Streams_whenPrepending_thenResultStreamContainsAllElements</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> seq <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token string">"bar"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> openingBracketSeq <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"["</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> closingBracketSeq <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"]"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 Stream<span class="token operator">&lt;</span>String<span class="token operator">></span> resultingStream <span class="token operator">=</span> Seq<span class="token punctuation">.</span><span class="token function">ofType</span><span class="token punctuation">(</span>seq<span class="token punctuation">,</span> String<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>closingBracketSeq<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">prepend</span><span class="token punctuation">(</span>openingBracketSeq<span class="token punctuation">)</span><span class="token punctuation">;</span>

 Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>
   Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"["</span><span class="token punctuation">,</span> <span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token string">"bar"</span><span class="token punctuation">,</span> <span class="token string">"]"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
   resultingStream<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="使用索引对流进行迭代"><a href="#使用索引对流进行迭代" class="headerlink" title="使用索引对流进行迭代"></a>使用索引对流进行迭代</h2><p>Java 8 Streams不是集合，因而无法使用索引来访问其中的元素，但是仍然有一些技巧可以实现这一点。</p>
<h4 id="使用原生Java"><a href="#使用原生Java" class="headerlink" title="使用原生Java"></a>使用原生Java</h4><p>由于原始元素位于可通过索引访问的数组或集合中，我们可以通过一定范围内的整数来访问流元素。<br>下面我们得到一个字符串数组，并且只选出被索引指向的字符串：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> List<span class="token operator">&lt;</span>String<span class="token operator">></span> <span class="token function">getEvenIndexedStrings</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> names<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> evenIndexedNames <span class="token operator">=</span> IntStream
   <span class="token punctuation">.</span><span class="token function">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> names<span class="token punctuation">.</span>length<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>i <span class="token operator">-</span><span class="token operator">></span> i <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">mapToObj</span><span class="token punctuation">(</span>i <span class="token operator">-</span><span class="token operator">></span> names<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token keyword">return</span> evenIndexedNames<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>可以通过以下代码测试：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCalled_thenReturnListOfEvenIndexedStrings</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 String<span class="token punctuation">[</span><span class="token punctuation">]</span> names 
   <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Bashkim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Lulzim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">,</span> <span class="token string">"Shpetim"</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> expectedResult 
   <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> actualResult 
   <span class="token operator">=</span> StreamIndices<span class="token punctuation">.</span><span class="token function">getEvenIndexedStrings</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">,</span> actualResult<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="使用-StreamUtils"><a href="#使用-StreamUtils" class="headerlink" title="使用 StreamUtils"></a>使用 StreamUtils</h4><p>使用索引进行迭代的另一种方式是使用proton-pack库中的StreamUtils工具类，其中的zipWithIndex()方法(可以在<a target="_blank" rel="noopener" href="https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.codepoetics%22%20AND%20a%3A%22protonpack%22">这里</a>找到最新版本)。<br>早pom文件中增加以下配置导入依赖：</p>
<pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>com.codepoetics<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>protonpack<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.13<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span></code></pre>
<p>使用方式如下：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> List<span class="token operator">&lt;</span>Indexed<span class="token operator">&lt;</span>String<span class="token operator">>></span> <span class="token function">getEvenIndexedStrings</span><span class="token punctuation">(</span>List<span class="token operator">&lt;</span>String<span class="token operator">></span> names<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 List<span class="token operator">&lt;</span>Indexed<span class="token operator">&lt;</span>String<span class="token operator">>></span> list <span class="token operator">=</span> StreamUtils
   <span class="token punctuation">.</span><span class="token function">zipWithIndex</span><span class="token punctuation">(</span>names<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>i <span class="token operator">-</span><span class="token operator">></span> i<span class="token punctuation">.</span><span class="token function">getIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token keyword">return</span> list<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>测试：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCalled_thenReturnListOfEvenIndexedStrings</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> names <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>
   <span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Bashkim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Lulzim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">,</span> <span class="token string">"Shpetim"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>Indexed<span class="token operator">&lt;</span>String<span class="token operator">>></span> expectedResult <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>
   Indexed<span class="token punctuation">.</span><span class="token function">index</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">"Afrim"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> 
   Indexed<span class="token punctuation">.</span><span class="token function">index</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> 
   Indexed<span class="token punctuation">.</span><span class="token function">index</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>Indexed<span class="token operator">&lt;</span>String<span class="token operator">>></span> actualResult 
   <span class="token operator">=</span> StreamIndices<span class="token punctuation">.</span><span class="token function">getEvenIndexedStrings</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">,</span> actualResult<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="使用-StreamEx"><a href="#使用-StreamEx" class="headerlink" title="使用 StreamEx"></a>使用 StreamEx</h4><p>使用StreamEx中EntryStream提供的方法<em>filterKeyValue()</em> 可以依照索引进行迭代。<br>pom依赖：</p>
<pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>one.util<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>streamex<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.6.5<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span></code></pre>
<p>实现与前面演示相同功能：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> List<span class="token operator">&lt;</span>String<span class="token operator">></span> <span class="token function">getEvenIndexedStringsVersionTwo</span><span class="token punctuation">(</span>List<span class="token operator">&lt;</span>String<span class="token operator">></span> names<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> EntryStream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">filterKeyValue</span><span class="token punctuation">(</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> name<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> index <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>对其进行测试：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCalled_thenReturnListOfEvenIndexedStringsVersionTwo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 String<span class="token punctuation">[</span><span class="token punctuation">]</span> names 
   <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Bashkim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Lulzim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">,</span> <span class="token string">"Shpetim"</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> expectedResult 
   <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> actualResult 
   <span class="token operator">=</span> StreamIndices<span class="token punctuation">.</span><span class="token function">getEvenIndexedStrings</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">assertEquals</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">,</span> actualResult<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="使用-Vavr中的Stream"><a href="#使用-Vavr中的Stream" class="headerlink" title="使用 Vavr中的Stream"></a>使用 Vavr中的Stream</h4><p>还可以使用Vavr的Stream类中的<em>zipWithIndex()</em> 方法。<br>引入依赖：</p>
<pre class=" language-java"><code class="language-java"><span class="token operator">&lt;</span>dependency<span class="token operator">></span>
 <span class="token operator">&lt;</span>groupId<span class="token operator">></span>io<span class="token punctuation">.</span>vavr<span class="token operator">&lt;</span><span class="token operator">/</span>groupId<span class="token operator">></span>
 <span class="token operator">&lt;</span>artifactId<span class="token operator">></span>vavr<span class="token operator">&lt;</span><span class="token operator">/</span>artifactId<span class="token operator">></span>
 <span class="token operator">&lt;</span>version<span class="token operator">></span><span class="token number">0.9</span><span class="token punctuation">.</span><span class="token number">0</span><span class="token operator">&lt;</span><span class="token operator">/</span>version<span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span>dependency<span class="token operator">></span></code></pre>
<p>实现相同功能</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> List<span class="token operator">&lt;</span>String<span class="token operator">></span> <span class="token function">getOddIndexedStringsVersionTwo</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> names<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> Stream
   <span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">zipWithIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>tuple <span class="token operator">-</span><span class="token operator">></span> tuple<span class="token punctuation">.</span>_2 <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>tuple <span class="token operator">-</span><span class="token operator">></span> tuple<span class="token punctuation">.</span>_1<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">toJavaList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>测试：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenCalled_thenReturnListOfOddStringsVersionTwo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 String<span class="token punctuation">[</span><span class="token punctuation">]</span> names 
   <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">"Afrim"</span><span class="token punctuation">,</span> <span class="token string">"Bashkim"</span><span class="token punctuation">,</span> <span class="token string">"Besim"</span><span class="token punctuation">,</span> <span class="token string">"Lulzim"</span><span class="token punctuation">,</span> <span class="token string">"Durim"</span><span class="token punctuation">,</span> <span class="token string">"Shpetim"</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> expectedResult 
   <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"Bashkim"</span><span class="token punctuation">,</span> <span class="token string">"Lulzim"</span><span class="token punctuation">,</span> <span class="token string">"Shpetim"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 List<span class="token operator">&lt;</span>String<span class="token operator">></span> actualResult 
   <span class="token operator">=</span> StreamIndices<span class="token punctuation">.</span><span class="token function">getOddIndexedStringsVersionTwo</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertEquals</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">,</span> actualResult<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="将Iterable-转换为-Stream"><a href="#将Iterable-转换为-Stream" class="headerlink" title="将Iterable_转换为_Stream"></a><strong>将<em>Iterable_转换为_Stream</em></strong></h2><p>Iterable接口在设计时考虑了通用性，没有在其中添加stream()方法。但是我们可以将其传递给StreamSupport.stream()方法，然后从传入的Iterable实例中获取一个流。<br>假设我们有一个Iterable实例：</p>
<pre class=" language-java"><code class="language-java">Iterable<span class="token operator">&lt;</span>String<span class="token operator">></span> iterable <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"Testing"</span><span class="token punctuation">,</span> <span class="token string">"Iterable"</span><span class="token punctuation">,</span> <span class="token string">"conversion"</span><span class="token punctuation">,</span> <span class="token string">"to"</span><span class="token punctuation">,</span> <span class="token string">"Stream"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>我们通过以下方式将其转换为流：</p>
<pre class=" language-java"><code class="language-java">StreamSupport<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span>iterable<span class="token punctuation">.</span><span class="token function">spliterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>该方法的第二个参数决定返回的结果流是不是并行流，如果参数为true，则返回并行流。<br>补充一个简短的说明——流不可重用，但是Iterable可重用； 它还提供了spliterator()方法，该方法在Iterable所描述的元素上返回一个Spliterator实例。<br>测试代码如下：</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whenConvertedToList_thenCorrect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 Iterable<span class="token operator">&lt;</span>String<span class="token operator">></span> iterable <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token string">"Testing"</span><span class="token punctuation">,</span> <span class="token string">"Iterable"</span><span class="token punctuation">,</span> <span class="token string">"conversion"</span><span class="token punctuation">,</span> <span class="token string">"to"</span><span class="token punctuation">,</span> <span class="token string">"Stream"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 List<span class="token operator">&lt;</span>String<span class="token operator">></span> result <span class="token operator">=</span> StreamSupport<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span>iterable<span class="token punctuation">.</span><span class="token function">spliterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>String<span class="token operator">:</span><span class="token operator">:</span>toUpperCase<span class="token punctuation">)</span>
   <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

 <span class="token function">assertThat</span><span class="token punctuation">(</span>
   result<span class="token punctuation">,</span> <span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">"TESTING"</span><span class="token punctuation">,</span> <span class="token string">"ITERABLE"</span><span class="token punctuation">,</span> <span class="token string">"CONVERSION"</span><span class="token punctuation">,</span> <span class="token string">"TO"</span><span class="token punctuation">,</span> <span class="token string">"STREAM"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="对流进行debug-peek-方法"><a href="#对流进行debug-peek-方法" class="headerlink" title="对流进行debug-peek()方法"></a>对流进行debug-peek()方法</h2><p>peek()方法的Javadoc页面有说明:“该方法的存在主要是为了支持调试过程中，您希望在元素流经管道中的某个节点时观察它们的情况”。<br>可以查看下面的代码：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">"one"</span><span class="token punctuation">,</span> <span class="token string">"two"</span><span class="token punctuation">,</span> <span class="token string">"three"</span><span class="token punctuation">,</span> <span class="token string">"four"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>e <span class="token operator">-</span><span class="token operator">></span> e<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">peek</span><span class="token punctuation">(</span>e <span class="token operator">-</span><span class="token operator">></span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Filtered value: "</span> <span class="token operator">+</span> e<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>String<span class="token operator">:</span><span class="token operator">:</span>toUpperCase<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">peek</span><span class="token punctuation">(</span>e <span class="token operator">-</span><span class="token operator">></span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Mapped value: "</span> <span class="token operator">+</span> e<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>这段代码演示了我们如何观察传递到某个节点的元素。<br>此外，peek()方法在另外一个场景下也很有用：需要改变元素的内部状态时。举例来说，如果我们想要在最终的打印操作之前，将用户的姓名转为小写，可以使用下面的代码：</p>
<pre class=" language-java"><code class="language-java">Stream<span class="token operator">&lt;</span>User<span class="token operator">></span> userStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token string">"Alice"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token string">"Bob"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token string">"Chuck"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
userStream<span class="token punctuation">.</span><span class="token function">peek</span><span class="token punctuation">(</span>u <span class="token operator">-</span><span class="token operator">></span> u<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span>u<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>System<span class="token punctuation">.</span>out<span class="token operator">:</span><span class="token operator">:</span>println<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="对流中的数值元素求和"><a href="#对流中的数值元素求和" class="headerlink" title="对流中的数值元素求和"></a>对流中的数值元素求和</h2><h4 id="使用Stream-reduce"><a href="#使用Stream-reduce" class="headerlink" title="使用Stream.reduce()"></a>使用Stream.reduce()</h4><p>Stream.reduce()是一个终结操作，对流中的元素执行归集运算。<br>在该操作中，可以对流中的每个元素应用二进制操作符（累加器），其中第一个操作数是前一次运算的结果，第二个操作数是当前流元素。<br>可以使用一个lambda表达式，将两个整数相加并返回求和后整数值：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Integer<span class="token operator">></span> integers <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Integer sum <span class="token operator">=</span> integers<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> a <span class="token operator">+</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>此外，也可以使用Java中已有的方法：</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Integer<span class="token operator">></span> integers <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Integer sum <span class="token operator">=</span> integers<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> Integer<span class="token operator">:</span><span class="token operator">:</span>sum<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>当然，也可以自定义的求和方法：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ArithmeticUtils</span> <span class="token punctuation">{</span>
 <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span> <span class="token keyword">int</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
     <span class="token keyword">return</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</li>
</ol>
<p>// 将上面的函数作为参数传入reduce()方法<br>List<integer> integers = Arrays.asList(1, 2, 3, 4, 5);<br>Integer sum = integers.stream()<br>  .reduce(0, ArithmeticUtils::add);</integer></p>
<pre><code>#### 使用Stream.collect()
```java
List&lt;Integer&gt; integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = integers.stream()
  .collect(Collectors.summingInt(Integer::intValue));</code></pre>
<p>Collectors中也提供了<em>summingLong()</em> 和<em>summingDouble()</em> 方法来分别计算long和double的和。</p>
<h4 id="使用IntStream-sum"><a href="#使用IntStream-sum" class="headerlink" title="使用IntStream.sum()"></a>使用IntStream.sum()</h4><p>Stream API为我们提供了mapToInt()中间操作，该操作将我们的流转换为IntStream对象。<br>该方法将一个映射器作为参数，用于进行转换，然后我们可以调用sum()方法来计算流元素的总和。</p>
<pre class=" language-java"><code class="language-java">List<span class="token operator">&lt;</span>Integer<span class="token operator">></span> integers <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Integer sum <span class="token operator">=</span> integers<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>Integer<span class="token operator">:</span><span class="token operator">:</span>intValue<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="使用Stream中的sum操作处理Object元素"><a href="#使用Stream中的sum操作处理Object元素" class="headerlink" title="使用Stream中的sum操作处理Object元素"></a>使用Stream中的sum操作处理Object元素</h4><p>假设我们有一个对象列表，并且想计算所有这些对象中给定字段的取值的总和。<br>举例来说，有下面的类：</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Item</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> Integer price<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">Item</span><span class="token punctuation">(</span><span class="token keyword">int</span> id<span class="token punctuation">,</span> Integer price<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>id <span class="token operator">=</span> id<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>price <span class="token operator">=</span> price<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// Standard getters and setters</span>
<span class="token punctuation">}</span></code></pre>
<p>然后，我们有该类的对象列表，并且要计算其中所有项的价格总和：</p>
<pre class=" language-java"><code class="language-java">Item item1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Item</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Item item2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Item</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Item item3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Item</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Item item4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Item</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

List<span class="token operator">&lt;</span>Item<span class="token operator">></span> items <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>item1<span class="token punctuation">,</span> item2<span class="token punctuation">,</span> item3<span class="token punctuation">,</span> item4<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>可以进行如下处理：</p>
<pre class=" language-java"><code class="language-java">Integer sum <span class="token operator">=</span> items<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>x <span class="token operator">-</span><span class="token operator">></span> x<span class="token punctuation">.</span><span class="token function">getPrice</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">summingInt</span><span class="token punctuation">(</span>Integer<span class="token operator">:</span><span class="token operator">:</span>intValue<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>或</p>
<pre class=" language-java"><code class="language-java">items<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">mapToInt</span><span class="token punctuation">(</span>x <span class="token operator">-</span><span class="token operator">></span> x<span class="token punctuation">.</span><span class="token function">getPrice</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>

            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">Guo Yaxiang</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://www.codinghonest.space/posts/108cf37c.html">https://www.codinghonest.space/posts/108cf37c.html</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">Guo Yaxiang</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/Java-Stream/">
                                    <span class="chip bg-color">Java Stream</span>
                                </a>
                            
                                <a href="/tags/%E5%87%BD%E6%95%B0%E5%BC%8F/">
                                    <span class="chip bg-color">函数式</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/medias/reward/alipay.png" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    
        <style>
    .mvaline-card {
        margin: 1.5rem auto;
    }

    .mvaline-card .card-content {
        padding: 20px 20px 5px 20px;
    }
</style>

<div class="card mvaline-card" data-aos="fade-up">
    <div class="comment_headling" style="font-size: 20px; font-weight: 700; position: relative; padding-left: 20px; top: 15px; padding-bottom: 5px;">
        <i class="fas fa-comments fa-fw" aria-hidden="true"></i>
        <span>评论</span>
    </div>
    <div id="mvcomments" class="card-content" style="display: grid">
    </div>
</div>

<script src="/libs/minivaline/MiniValine.js"></script>
<script>
    new MiniValine({
        el: '#mvcomments',
        appId: 'oqAo7rCWejwTqHjGC2APTVDX-MdYXbMMI',
        appKey: 'pfyY919tO7iJaDm7lFmvh5Wp',
        mode: 'DesertsP',
        placeholder: 'Write a Comment',
        pathname: window.location.pathname,
        lang: '',
        adminEmailMd5: '8BBC105436DAAF8C803841C8FD13CD0C',
        tagMeta: ["管理员", "小伙伴", "访客"],
        master: ["8BBC105436DAAF8C803841C8FD13CD0C"],
        friends: ["FA21C7921CD42FE9523E957870873F64", "586BAB41BB5692877F7714DFE4947DEC"],
        math: true,
        md: true,
        enableQQ: false,
        NoRecordIP: false,
        visitor: true,
        maxNest: 6,
        pageSize: 6,
        serverURLs: '',
        emoticonUrl: ["https://cdn.jsdelivr.net/npm/alus@latest", "https://cdn.jsdelivr.net/gh/MiniValine/qq@latest", "https://cdn.jsdelivr.net/gh/MiniValine/Bilibilis@latest", "https://cdn.jsdelivr.net/gh/MiniValine/tieba@latest", "https://cdn.jsdelivr.net/gh/MiniValine/twemoji@latest", "https://cdn.jsdelivr.net/gh/MiniValine/weibo@latest"],
    });
</script>

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/posts/772d24e8.html">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/6.jpg" class="responsive-img" alt="实现Raft协议：Part 0 - 介绍">
                        
                        <span class="card-title">实现Raft协议：Part 0 - 介绍</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            本系列文章的写作目的，在于描述Raft协议的一个功能完备且经过严格测试的实现方式，并提供一些Raft工作方式的直观理解。
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2021-03-04
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/%E5%88%86%E5%B8%83%E5%BC%8F/" class="post-category">
                                    分布式
                                </a>
                            
                            <a href="/categories/%E5%88%86%E5%B8%83%E5%BC%8F/%E4%B8%80%E8%87%B4%E6%80%A7%E5%8D%8F%E8%AE%AE/" class="post-category">
                                    一致性协议
                                </a>
                            
                            <a href="/categories/%E5%88%86%E5%B8%83%E5%BC%8F/%E4%B8%80%E8%87%B4%E6%80%A7%E5%8D%8F%E8%AE%AE/Raft/" class="post-category">
                                    Raft
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%B8%80%E8%87%B4%E6%80%A7/">
                        <span class="chip bg-color">分布式一致性</span>
                    </a>
                    
                    <a href="/tags/Raft/">
                        <span class="chip bg-color">Raft</span>
                    </a>
                    
                    <a href="/tags/%E8%AF%91%E6%96%87/">
                        <span class="chip bg-color">译文</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/posts/9739b154.html">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/4.jpg" class="responsive-img" alt="Java 8 Stream API详解( 二)——Stream Collectors">
                        
                        <span class="card-title">Java 8 Stream API详解( 二)——Stream Collectors</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            本系列主要用于记录关于Stream API的一些学习笔记，用于自己以后复习，也希望可以帮助到其他人。
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2021-01-18
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/Java/" class="post-category">
                                    Java
                                </a>
                            
                            <a href="/categories/Java/Stream/" class="post-category">
                                    Stream
                                </a>
                            
                            <a href="/categories/Java/Stream/%E5%87%BD%E6%95%B0%E5%BC%8F/" class="post-category">
                                    函数式
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/Java-Stream/">
                        <span class="chip bg-color">Java Stream</span>
                    </a>
                    
                    <a href="/tags/%E5%87%BD%E6%95%B0%E5%BC%8F/">
                        <span class="chip bg-color">函数式</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>


<script>
    $('#articleContent').on('copy', function (e) {
        // IE8 or earlier browser is 'undefined'
        if (typeof window.getSelection === 'undefined') return;

        var selection = window.getSelection();
        // if the selection is short let's not annoy our users.
        if (('' + selection).length < Number.parseInt('120')) {
            return;
        }

        // create a div outside of the visible area and fill it with the selected text.
        var bodyElement = document.getElementsByTagName('body')[0];
        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        bodyElement.appendChild(newdiv);
        newdiv.appendChild(selection.getRangeAt(0).cloneContents());

        // we need a <pre> tag workaround.
        // otherwise the text inside "pre" loses all the line breaks!
        if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'PRE') {
            newdiv.innerHTML = "<pre>" + newdiv.innerHTML + "</pre>";
        }

        var url = document.location.href;
        newdiv.innerHTML += '<br />'
            + '来源: 码道诚公<br />'
            + '文章作者: Guo Yaxiang<br />'
            + '文章链接: <a href="' + url + '">' + url + '</a><br />'
            + '本文章著作权归作者所有，任何形式的转载都请注明出处。';

        selection.selectAllChildren(newdiv);
        window.setTimeout(function () {bodyElement.removeChild(newdiv);}, 200);
    });
</script>


<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


<!-- 代码块折行 -->

<style type="text/css">
code[class*="language-"], pre[class*="language-"] { white-space: pre !important; }
</style>


    

</main>




    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="503838841"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/libs/aplayer/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>

    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2020-2021</span>
            
            <span id="year">2020</span>
            <a href="/about" target="_blank">Guo Yaxiang</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
            
            
            
            
            <br>
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link ">
    <a href="https://github.com/GuoYaxiang" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="mailto:YXGyxg112358@163.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=1431800679" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 1431800679" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>





    <a href="https://www.zhihu.com/people/guo-ya-xiang" class="tooltipped" target="_blank" data-tooltip="关注我的知乎: https://www.zhihu.com/people/guo-ya-xiang" data-position="top" data-delay="50">
        <i class="fab fa-zhihu1">知</i>
    </a>



    <a href="/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50">
        <i class="fas fa-rss"></i>
    </a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script src="/js/search.js"></script>
<script type="text/javascript">
$(function () {
    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    

    
        <script src="//code.tidio.co/zgiqinzrat1rzwxseqhr2pnzsp2a4rjo.js"></script>
        <script>
            $(document).ready(function () {
                setInterval(change_Tidio, 50);
                function change_Tidio() {
                    var tidio=$("#tidio-chat iframe");
                    if(tidio.css("display")=="block"&& $(window).width()>977 ){
                        document.getElementById("tidio-chat-iframe").style.bottom= ($("div#backTop.top-scroll").css("display")=="none" &&$(window).width()>977)>0? "-40px" : ($("div.toc-title").length&&$(window).width()>977)>0?"85px":"20px";
                        document.getElementById("tidio-chat-iframe").style.right="-15px";
                        document.getElementById("tidio-chat-iframe").style.height=parseInt(tidio.css("height"))>=520?"520px":tidio.css("height");
                        document.getElementById("tidio-chat-iframe").style.zIndex="997";
                    }
                    else if(tidio.css("display")=="block"&&$(window).width()>601 &&$(window).width()<992 ){
                        document.getElementById("tidio-chat-iframe").style.bottom= ($("div#backTop.top-scroll").css("display")=="none" && 601< $(window).width()<992)>0? "-40px":"20px" ;
                        document.getElementById("tidio-chat-iframe").style.right="-15px";
                        document.getElementById("tidio-chat-iframe").style.zIndex="997";
                    }
                    else if(tidio.css("display")=="block"&&$(window).width()<601 && parseInt(tidio.css("height"))<230){
                        document.getElementById("tidio-chat-iframe").style.bottom= ($("div#backTop.top-scroll").css("display")=="none" && $(window).width()<601)>0? "-10px":"45px" ;
                        document.getElementById("tidio-chat-iframe").style.zIndex="997";
                    }
                    if( tidio.css("display")=="block"&&$(window).width()<601 && parseInt(tidio.css("height"))>=230){
                        document.getElementById("tidio-chat-iframe").style.zIndex="998";
                    }
                }
            });
        </script>
    

    

    

    

    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    

</body>

</html>
